﻿/*	@file	r_math_matrix44.h
	@brief	行列
Copyright (c) 2009 Yuya Yamaguchi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _R_MATH_MATRIX44_H_
#define _R_MATH_MATRIX44_H_


#include "r_math_def.h"

namespace r{
	namespace math{

		struct Vector2D;
		struct Vector3D;
		struct Vector4D;
		struct Matrix33;
		struct Matrix34;


		///
		struct Matrix44 {
		public:
			//! コンストラクタ
			Matrix44 ( void );
			Matrix44 ( r_f32 val );
			Matrix44 (
				r_f32 s11, r_f32 s12, r_f32 s13, r_f32 s14,
				r_f32 s21, r_f32 s22, r_f32 s23, r_f32 s24,
				r_f32 s31, r_f32 s32, r_f32 s33, r_f32 s34,
				r_f32 s41, r_f32 s42, r_f32 s43, r_f32 s44 );
			Matrix44 ( const r_f32* sv );
			Matrix44 ( const r::math::Matrix33& rot, const r::math::Vector3D& pos );
			//! 単位行列の作成
			void	identity ( void );
		public:
			//! エイミング
			/*!
			*/
			void	aim ( const r::math::Vector3D& position, const r::math::Vector3D& target, const r::math::Vector3D& upvector );
			//! ビュー変換(左手)
			/***/
			void	lookAt_L ( const r::math::Vector3D& position, const r::math::Vector3D& target, const r::math::Vector3D& upvector );
			//! ビュー変換(右手)
			/***/
			void	lookAt_R ( const r::math::Vector3D& position, const r::math::Vector3D& target, const r::math::Vector3D& upvector );
			//! パースペクティブ変換(左手座標系)
			/***/
			void	perspective_L ( r_f32 width, r_f32 height, r_f32 znearPlane, r_f32 zfarPlane );
			//! パースペクティブ変換(右手座標系)
			/***/
			void	perspective_R ( r_f32 width, r_f32 height, r_f32 znearPlane, r_f32 zfarPlane );
			//! パースペクティブ変換(左手座標系)
			/***/
			void	perspectiveFov_L ( r_f32 fieldOfViewY, r_f32 aspectRatio, r_f32 znearPlane, r_f32 zfarPlane );
			//! パースペクティブ変換(右手座標系)
			/***/
			void	perspectiveFov_R ( r_f32 fieldOfViewY, r_f32 aspectRatio, r_f32 znearPlane, r_f32 zfarPlane );
			//! オーソグラフィクス変換
			/***/
			void	orthographics_L ( r_f32 width, r_f32 height, r_f32 znearPlane, r_f32 zfarPlane );
			void	orthographics_R ( r_f32 width, r_f32 height, r_f32 znearPlane, r_f32 zfarPlane );
			void	orthographics_L ( r_f32 x, r_f32 y, r_f32 width, r_f32 height, r_f32 znearPlane, r_f32 zfarPlane );
			void	orthographics_R ( r_f32 x, r_f32 y, r_f32 width, r_f32 height, r_f32 znearPlane, r_f32 zfarPlane );
		public:
			//! 行列の有効箇所が3x4とみなしての行列合成
			inline void mulFast ( Matrix44& dest, const Matrix44& src ) const;
			//! 行列の合成
			inline void mul ( Matrix44& dest, const Matrix44& src ) const;
			//! 行列の合成
			Matrix44 operator * ( const Matrix44& src ) const;
			const Matrix44& operator *= ( const Matrix44& src );
			//! 行列の全成分に引数srcを掛け合わせる
			Matrix44 operator * ( r_f32 src ) const;
			const Matrix44& operator *= ( r_f32 src );
			//! 行列の加算
			Matrix44 operator + ( const Matrix44& src ) const;
			const Matrix44& operator += ( const Matrix44& src );
			//! 行列の転置(移動値が逆行列化する)
			void	transposeInverse ( void );
			//! 行列の転置(シェーダでdot積で計算する為)
			void	transpose ( void );
			//! 行列の転置(シェーダでdot積で計算する為3x4行列とコンパチインターフェース)
			void	transpose ( Matrix44& dst );
			//! 逆行列
			void	inverse ( void );
			//! 移動行列の作成
			const Matrix44& translate ( const r::math::Vector3D& src );
			//! 現在の行列の移動成分のみを設定する
			const Matrix44& setTranslate ( const r::math::Vector3D& src );
			//! スケール行列の作成
			const Matrix44& scale ( const r::math::Vector3D& src );
			const Matrix44& scale ( r_f32 src );
			//! X軸回転の行列を設定
			/*!
			@param	src	[in]	x軸での回転(ラジアン)
			*/
			const Matrix44& rotateX ( r_f32 src );
			//! Y軸回転の行列を設定
			/*!
			@param	src	[in]	y軸での回転(ラジアン)
			*/
			const Matrix44& rotateY ( r_f32 src );
			//! Z軸回転の行列を設定
			/*!
			@param	src	[in]	z軸での回転(ラジアン)
			*/
			const Matrix44& rotateZ ( r_f32 src );
			//! 任意軸での回転行列を設定
			/*!
			@param	vec	[in]	回転軸
			@param	rot	[in]	回転量(ラジアン)
			*/
			const Matrix44& rotateAxis ( const r::math::Vector3D& vec, r_f32 rot );
			//! 3x3行列成分の抽出
			operator r::math::Matrix33 ( void ) const;
			//! 3x4行列成分の抽出
			operator r::math::Matrix34 ( void ) const;
			//! 行列の回転成分のみ設定する
			const Matrix44& setRotateAxis ( const r::math::Matrix33& rot );
			//! ベクトルを行列で変換
			r::math::Vector3D	transform3D ( const r::math::Vector2D& vec ) const;
			r::math::Vector3D	transform3D ( const r::math::Vector3D& vec ) const;
			r::math::Vector3D	transform3D33 ( const r::math::Vector3D& vec ) const;
			r::math::Vector4D	transform4D ( const r::math::Vector3D& vec ) const;
			r::math::Vector4D	transform4D ( const r::math::Vector4D& vec ) const;
			//! 行列の各回転成分のスケールを1.0に正規化する
			const Matrix44	&normalize ( void );
			//! 行列のスケールを取得
			r::math::Vector3D getSize ( void ) const;
			//! 構成成分のオイラー角を取得
			r::math::Vector3D	EulerXYZ ( void ) const;
			r::math::Vector3D	EulerXZY ( void ) const;
			r::math::Vector3D	EulerYXZ ( void ) const;
			r::math::Vector3D	EulerYZX ( void ) const;
			r::math::Vector3D	EulerZXY ( void ) const;
			r::math::Vector3D	EulerZYX ( void ) const;
			//! XYZ軸に対してオイラー角3つを指定して回転行列を作成する
			/*! いずれは展開したいです*/
			const Matrix44& rotateXYZ ( const r::math::Vector3D& rot );
			const Matrix44& rotateXZY ( const r::math::Vector3D& rot );
			const Matrix44& rotateYXZ ( const r::math::Vector3D& rot );
			const Matrix44& rotateYZX ( const r::math::Vector3D& rot );
			const Matrix44& rotateZXY ( const r::math::Vector3D& rot );
			const Matrix44& rotateZYX ( const r::math::Vector3D& rot );
			union {
				struct {
					r_f32		_11;
					r_f32		_12;
					r_f32		_13;
					r_f32		_14;
					r_f32		_21;
					r_f32		_22;
					r_f32		_23;
					r_f32		_24;
					r_f32		_31;
					r_f32		_32;
					r_f32		_33;
					r_f32		_34;
					r_f32		_41;
					r_f32		_42;
					r_f32		_43;
					r_f32		_44;
				};
				r_f32			m[4][4];
				r_f32			f[16];
			};
		};
	}
}
#include "../rtti/r_rtti_reflection_typename.h"
namespace r{
	namespace rtti{
		//! r::math::Matrix44
		template<>
		static inline
		const r_cstr	getTypeNameStr<r::math::Matrix44>() {
			return _RST ( "r::math::Matrix44" );
		}
	}
}

#endif // _R_MATH_MATRIX44_H_
